package train;

import java.util.ArrayList;
import java.util.Random;

import jonctions.Aiguillage;
import jonctions.Butee;
import jonctions.JonctionSimple;
import rail.Rail;
import reseau.ReseauFerre;
import semaphore.Semaphore;
import capteur.Capteur;
import capteur.CapteurPresence;
import exceptions.ExceptionCollision;
import exceptions.ExceptionDeraillement;

public class Train {

	private int idTrain;
	private int taille;
	private double vitesseMax;
	private double vitesseActuel;
	private boolean sensDeplacement;
	private int positionTete;
	private int positionQueu;

	private ArrayList<Rail> listRailTrain; /* contient les rails sous le train */
	private ArrayList<Capteur> listCaptTrain;

	public void setPositionQueu(int positionQueu) {
		this.positionQueu = positionQueu;
	}

	public int getPositionTete() {
		return positionTete;
	}

	public int getPositionQueu() {
		return positionQueu;
	}

	public boolean isSensDeplacement() {
		return sensDeplacement;
	}

	public Train(int idTrain, Butee butee) {
		this.idTrain = idTrain;
		Random r = new Random();
		this.taille = ReseauFerre.MINTAILLETRAIN
				+ r.nextInt(ReseauFerre.MAXTAILLETRAIN
						- ReseauFerre.MINTAILLETRAIN);
		this.vitesseMax = ReseauFerre.MINVITESSETRAIN
				+ r.nextInt(ReseauFerre.MAXVITESSETRAIN
						- ReseauFerre.MINVITESSETRAIN);
		this.vitesseActuel = this.vitesseMax;
		this.sensDeplacement = true;
		this.positionTete = this.taille;
		this.positionQueu = 0;
		this.listRailTrain = new ArrayList<Rail>();
		this.listRailTrain.add(butee.getListRail().get(0));

	}

	/* ajoute un rail à listRailTrain */
	public void prochainRailTrain(Rail r) {

		this.listRailTrain.add(r);

		updateRailTrain();

	}

	/*
	 * supp les rails inutile (qui ne sont pas endessous du train) de
	 * listRailTrain
	 */
	public void updateRailTrain() {

		double tailleTmp = 0;
		int i = listRailTrain.size()-1;
		

	 

		System.out.println("nb de rail sous le train " + listRailTrain.size());
		
		
		
		
		/*
		if ((positionTete < taille)) { 
										 * on teste si le train est entre deux
										 * rails
										 

			 

			//tailleTmp = positionTete + listRailTrain.get(listRailTrain.size() - i).getLongueur();

			tailleTmp = positionTete +listRailTrain.get(1).getLongueur();
			
			while (tailleTmp < taille) { 
										 * cad que il manque un bout de train
										 * dans d'autre rail. tant qu'on
										 * n'arrive pas au rail qui contient la
										 * queu du train on continue à
										 * incrementer i
										 
			//	tailleTmp = tailleTmp + listRailTrain.get(listRailTrain.size() - i).getLongueur();
				if (tailleTmp > taille) { 
										 * si la tailleTmp est superieur à la
										 * taille du train alors on sait que la
										 * queue du train est sur cet rail
										 
					k = 0;
					while (i > 2) 
								 * on recopie les rails sous le train dans une
								 * arrayListe temporaire
								 
					{

						this.listRailTrain.remove(k);

						i--;
						k++;
					}

				} 
				else {
					i++; 
						 * on increment i car on est pas encore arrivé au vagon
						 * qui contient la queu du train
						 
					
				}

			}*/
			
			
			
			
			
		}
		
		
		 
		

	

	public int getId() {
		return idTrain;
	}

	/* ajoute un nouveau capteur dans listCapTrain */
	public void rechercheCapt(Rail r) {
		for (Capteur c : r.getListCaptRail()) {
			if (c.getPositionCapt() <= positionTete) {
				this.listCaptTrain.add(c);
			}
		}

	}

	/* supprime un capteur de listCapTrain */
	public void supprimeCapt() {

		for (Capteur c : listRailTrain.get(0).getListCaptRail()) { /*
																	 * on va au
																	 * dernier
																	 * rails et
																	 * on
																	 * cherche
																	 * si il a
																	 * des
																	 * capteur
																	 */
			if (c.getPositionCapt() < positionQueu) {/*
													 * on supprime si le capteur
													 * ne capte plus le train
													 */
				listCaptTrain.remove(c);/*
										 * a voir si on peut supprimer
										 * directement de cette manière
										 */
			}
		}
	}

	/* teste si le capteur est sous la tete du train */
	public boolean testCapTrain(Capteur c) {

		if (c.testePresenceTrain((int) positionTete)) {
			return true;
		}
		return false;
	}

	/* depalcement train par rapport au vitesse du train */
	public void deplacementTrain() throws ExceptionDeraillement {

		double distanceParcouru = 0;
		int m = 1;
		int deraillement = 0;
		distanceParcouru = this.vitesseActuel;
		int distanceTmp = (int) (vitesseActuel - (listRailTrain.get(
				listRailTrain.size() - 1).getLongueur() - positionTete));
		ArrayList<Rail> listRailJonction = new ArrayList<Rail>();
		Rail prochainRail = new Rail();
		int butee = 0;

		if (feu()) {

			
			
			
			// ************************************** choisir la prochaine jonction selon le sens de déplacement ***************************************************
			if (sensDeplacement) {
				
				listRailJonction = listRailTrain.get(listRailTrain.size() - 1)
						.getJonction2().getListRail();
				
				deraillement = listRailTrain.get(listRailTrain.size() - 1)
						.getJonction2().getId();
			
				
			} 
			
			
			else {
				listRailJonction = listRailTrain.get(listRailTrain.size() - 1)
						.getJonction1().getListRail();
				deraillement = listRailTrain.get(listRailTrain.size() - 1)
						.getJonction1().getId();
			}

			
			
			
			
			
			
			
			
			
			//************************************** Choisir le prochain rail selon le type de  jonction ***********************************
			
			
			if ((listRailJonction.size() == 2)) {// cas de Jonction de simple

				
				if (listRailJonction.get(0).getIdRail() != listRailTrain.get(listRailTrain.size() - 1).getIdRail()) {
					prochainRail = listRailJonction.get(0);
					System.out.println("rail nouveau " + listRailJonction.get(0).getIdRail());

				} else 
				{
					prochainRail = listRailJonction.get(1);
					System.out.println("rail actuel : " +listRailTrain.get(listRailTrain.size() - 1).getIdRail());
					System.out.println(" next rail , avec get 1 est :"  +listRailJonction.get(1).getIdRail());

				}

			}
			
			
			
			else if(listRailTrain.get(listRailTrain.size() - 1).getJonction1().getClass().toString().equals(Butee.class.toString()) && this.positionTete + this.vitesseActuel >= this.listRailTrain.get(this.listRailTrain.size()-1).getLongueur() ){
				
				listRailJonction = listRailTrain.get(listRailTrain.size() - 1)
						.getJonction2().getListRail();
			
				if (listRailJonction.get(0).getIdRail() != listRailTrain.get(listRailTrain.size()- 1).getIdRail()) {
					prochainRail = listRailJonction.get(0);
					System.out.println("::::::::::::::::::::  BUTEE    rail nouveau " + listRailJonction.get(0).getIdRail());

				} 
				else 
				{
					prochainRail = listRailJonction.get(1);
					System.out.println("rail actuel : " +listRailTrain.get(listRailTrain.size() - 1).getIdRail());
					System.out.println(" next rail , avec get 1 est :"  +listRailJonction.get(1).getIdRail());

				}
				
			
				this.positionTete=this.taille;
			
			}
			else if(listRailTrain.get(listRailTrain.size() - 1).getJonction2().getClass().toString().equals(Butee.class.toString())&& this.positionTete + this.vitesseActuel >= this.listRailTrain.get(this.listRailTrain.size()-1).getLongueur() ){
				
				listRailJonction = listRailTrain.get(listRailTrain.size() - 1)
						.getJonction1().getListRail();
			
				if (listRailJonction.get(0).getIdRail() != listRailTrain.get(listRailTrain.size()- 1).getIdRail()) {
					prochainRail = listRailJonction.get(0);
					System.out.println("::::::::::::::::::::  BUTEE    rail nouveau " + listRailJonction.get(0).getIdRail());

				} 
				else 
				{
					prochainRail = listRailJonction.get(1);
					System.out.println("rail actuel : " +listRailTrain.get(listRailTrain.size() - 1).getIdRail());
					System.out.println(" next rail , avec get 1 est :"  +listRailJonction.get(1).getIdRail());

				}
				
				
				this.positionTete=this.taille;
				
			
			}

			
			
			else { // cas ou c'est un aiguillage
				System.out.println("************ cas aiguillage ***********");
				Aiguillage ai = (Aiguillage) listRailTrain.get(
						listRailTrain.size() - 1).getJonction2();
				prochainRail = ai.getAval();

			}
			
			
			//************************************** FIN du choix du prochain rail selon la jonction ***********************************
			
			
			 
			System.out
					.println("la taille de la rail actuel :"
							+ listRailTrain.get(listRailTrain.size() - 1)
									.getLongueur());

			System.out.println("la taille du prochain rail : "
					+ prochainRail.getLongueur());
			System.out.println(  " 1/ id du prochain rail :" +listRailJonction.get(0).getIdRail());
			
		
			
			
			
			
			
			//************************************** Boucle de deplacement *******************************************************

			while (m == 1) {

				
				/********************************************  Cas ou on change de rail  **********************************************/
				if ((positionTete +vitesseActuel) > listRailTrain.get(listRailTrain.size() - 1).getLongueur()) {
																			  

					System.out.println("Id train actuelle " + idTrain+ " change de rail.-------");
					positionTete = (int) ((vitesseActuel + positionTete )- listRailTrain.get(listRailTrain.size() - 1).getLongueur()) ;
													/*
													 * on met la position de la
													 * tete du train au bout de
													 * la rail qu'on vien de le
													 * parcourir
													 */
					
					System.out.println(  " 2/id du prochain rail :" +listRailJonction.get(0).getIdRail());
					prochainRailTrain(listRailJonction.get(1));


				}
				
				
				/********************************************  Cas ou on reste sur le meme rail  **********************************************/
				else {

					
					if(positionTete<taille ){
						
						
					}
					
					
					
					if (listRailTrain.size() >= 2) {
						listRailTrain.remove(listRailTrain.size() - 2);
					}

					System.out.println(" on parcour  le meme rail  ");
					System.out.println("nb de rail sous le train "
							+ listRailTrain.size());

					positionQueu = (int) (positionQueu + vitesseActuel);
					positionTete = (int) (positionTete + vitesseActuel); 
					m = 2;/* on sort de la boucle */
					
					
				}

			}

			System.out
					.println("----------------------------------------------------------------");
			 

			/*
			 * else if ((listRailJonction.size() ==
			 * 1)||(prochainRail.getLongueur()==0)) {
			 * 
			 * if (deraillement == -1) { throw new ExceptionDeraillement(this);
			 * }
			 * 
			 * System.out.println("Le train " + this.idTrain + "a rencontre la "
			 * + this.listRailTrain.get(this.listRailTrain.size() - 1)
			 * .getJonction1().getClass().toString() + " numero " +
			 * this.listRailTrain.get(this.listRailTrain.size() - 1)
			 * .getJonction1().getId()); this.sensDeplacement = true;
			 * 
			 * this.positionQueu = 0; this.positionTete = taille;
			 * 
			 * 
			 * System.out.println("On a rencontré une butée+++++++++"); }
			 */

		}

		/*
		 * else if (listRailJonction.size() > 2) {
		 * 
		 * Aiguillage ai = (Aiguillage) listRailTrain.get( listRailTrain.size()
		 * - 1).getJonction2(); prochainRail = ai.getAval();
		 * 
		 * System.out.println("taille du train : " + taille); System.out
		 * .println("la taille de la rail actuel :" +
		 * listRailTrain.get(listRailTrain.size() - 1) .getLongueur());
		 * 
		 * System.out.println("la taille du prochain rail : " +
		 * prochainRail.getLongueur()); while (m == 1) {
		 * 
		 * if (positionTete > listRailTrain.get(listRailTrain.size() - 1)
		 * .getLongueur()) {
		 * 
		 * System.out.println("on change de rail.-------"); positionTete =
		 * positionTete - listRailTrain.get(listRailTrain.size() - 1)
		 * .getLongueur();
		 * 
		 * if (positionQueu > listRailTrain.get( listRailTrain.size() -
		 * 1).getLongueur()) { positionQueu = positionQueu -
		 * listRailTrain.get(listRailTrain.size() - 1) .getLongueur(); }
		 * 
		 * prochainRailTrain(listRailJonction.get(1));
		 * 
		 * } else { if (listRailTrain.size() == 2) {
		 * listRailTrain.remove(listRailTrain.size() - 1); }
		 * 
		 * System.out.println(" on parcour  le meme rail  ");
		 * System.out.println("nb de rail sous le train " +
		 * listRailTrain.size());
		 * 
		 * positionQueu = (int) (positionQueu + vitesseActuel); positionTete =
		 * (int) (positionTete + vitesseActuel);
		 * 
		 * m = 2; }
		 * 
		 * }
		 * 
		 * System.out .println(
		 * "-------------------------*********--------------------------------"
		 * );
		 * 
		 * }
		 */

	}

	public int getTaille() {
		return taille;
	}

	public void setTaille(int taille) {
		this.taille = taille;
	}

	public ArrayList<Rail> getListRailTrain() {
		return listRailTrain;
	}

	public double getVitesseActuel() {
		return vitesseActuel;
	}

	public boolean feu() {

		String rouge = new String("rouge");
		// Semaphore s = new Semaphore();

		if (listRailTrain.get(listRailTrain.size() - 1).getListSemaphoreRail()
				.size() > 0) {
			for (Semaphore s : listRailTrain.get(listRailTrain.size() - 1)
					.getListSemaphoreRail()) {
				System.out.println("boucle feu$$$$$$$$$$$$$$$$$");

				if (s.getPositionSema() == positionTete) {
					if (s.getEtat().getCouleur().equals("rouge")) {
						System.out
								.println("feu rouge ===================STOP============");
						vitesseActuel = 0;
						return false;
					} else if (s.getEtat().getCouleur().equals("vert")) {
						System.out
								.println("feu vert ==================GO===============");

						return true;
					} else if (s.getEtat().getCouleur().equals("orange")) {
						System.out
								.println("feu orange ==============Ralentir===========");
						vitesseActuel = vitesseActuel / 2;
						return true;
					}

				}
			}
		}
		System.out.println("Pas de feu ");
		return true;
	}

}
